DEPRECATED
==========

The `nvmutils` project is now discontinued. Newer development is now
done in `nvmutil`. Not to be confused. New project:

* <https://notabug.org/osboot/nvmutil/>

The `nvmutils` project shall be preserved, for reference, but all new
development should go in `nvmutil` instead.

nvmutils
========

This manual was last updated for nvmmac version 20220307,
released on 2022-03-07. These programs allow you to manipulate
Intel PHY NVM images, extracted from coreboot ROM images on
Intel machines with an Intel PHY and IFD (Intel Flash Descriptor).

Below, you will find instructions that teach you how to compile
the source code and make use of these programs. However, the first
sections will go into some detail about exactly what this program
is for, providing some background information about Intel PHY NVM
images used on Intel machines.

Download this software
----------------------

You can find newer versions of `nvmutils` by downloading it
from the official Git repository, like so:

    git clone https://notabug.org/osboot/nvmutils

Releases of nvmutils are *tagged*, so you can use `git tag` to find
which versions are officially available. You can switch to any
version, using `git reset`. More information about Git is available
on the Git homepage:

* <https://git-scm.com/>

The `nvmutils` software is an official project within *osboot*:

* <https://osboot.org/>

Introduction
============

On many Intel systems with an IFD (Intel Flash Descriptor), the
Intel PHY (Gigabit Ethernet) stores its configuration, binary
encoded, into a special region of the main boot flash, alongside
other flash regions such as: IFD, ME, BIOS.

This includes many configurations, such as your MAC address.
The purpose of `nvmmac`, supplied by the nvmutils project, is
precisely to allow you to change your MAC address. Many other
useful programs are also provided.

Intel defines this as the *Gigabit Ethernet Non-Volative Memory* or
just *NVM* for short. It is a 128-byte section, consisting of 64
words that are 2 bytes, stored in little-endian byte order.

Newer Intel PHYs define an *extended* area, which starts
immediately after the main one, but the `nvmutils` programs
do not modify or manipulate these in any way.

The final word in the NVM section is the *checksum*; all words
must add up, truncated, to the value `0xBABA`. The hardware
itself does not calculate or validate this, and will in
fact work nicely, but software such as Linux will check
that this is correct. If the checksum is invalid, your
kernel will refuse to make use of the NIC.

This NVM section is the first 128 bytes of a 4KB region in flash.
This 4KB region is then repeated, to make an 8KB region in
flash, known as the *GbE region*. In `nvmutils`, the first part
is referred to as *part 0* and the second part as *part 1*.

Known compatible PHYs
---------------------

TODO: write here what actual PHYs are known to work.

Free your BIOS today!
---------------------

This software is targeted at coreboot users, and users of
coreboot *distributions* such as osboot, but this is a universal
tool that is applicable to many Intel platforms, regardless of
whether the user has coreboot or not.

You can learn about coreboot and osboot on these websites:

* <https://coreboot.org/>
* <https://osboot.org/>

Coreboot is a free and open source firmware project, which has
support for many different kinds of computers. The osboot
project provides an easy-to-use automated build system and
friendly instructions for installing coreboot, for non-technical
users who may otherwise find coreboot quite daunting.

How to obtain the GbE file
==========================

The chip containing your BIOS/UEFI firmware (or coreboot) has
it, if you have an Intel PHY for gigabit ethernet.

The sections below will teach you how to obtain the GbE file,
containing your NIC's configuration. This is the part that
many people will struggle with, so we will dedicated an
entire next section to it:

Use flashrom
------------

If you wish to operate on the GbE section that's already
flashed, you should *dump* the current full ROM image.
If you already have a ROM image, you do not need to dump
it, so you can skip this section.

Download flashrom here:

* <https://flashrom.org/>

Using recent flashrom versions, you can extract this region. If
your regions are unlocked, you can run flashrom on the target
system, like so:

    flashrom -p internal -r rom.bin

If your system has two flash chips, the GbE region is usually
stored on SPI1 (not SPI2). Otherwise, it may be that you have
a single-flash setup. In that case, it's recommended to dump
both chips, as `spi1.rom` and `spi2.rom`; you can then cat
them together:

    cat spi1.rom spi2.rom > rom.bin

If your GbE region is locked (per IFD settings), you can dump
and flash it using external flashing equipment. The `osboot`
project has a handy guide for this; it can be used for reading
from and writing to the chip. See:

* <https://osboot.org/docs/install/spi.html>

If you're using an external programmer, the `-p internal`
option should be changed accordingly. Read flashrom
documentation, and make sure you have everything
properly configured.

Use ifdtool
-----------

The `ifdtool` program is a powerful tool, allowing you to
manipulate Intel Flash Descriptors. It's part of coreboot,
available in the `coreboot.git` repository
under `util/ifdtool/`. Just go in there and build it
with `make`, to get an ifdtool binary.

To make internal flashing possible later on, you might do:

    ifdtool --unlock rom.bin

Running this command will create a modified image,
named `rom.bin.new`. This file will have all regions set
to read-write, per configuration in the Intel Flash Descriptor.

In addition to unlocked regions, you may wish to *neuter* the
Intel Management Engine, removing all the nasty spying features
from it, using `me_cleaner`. See:

* <https://github.com/corna/me_cleaner>
* Also available in `coreboot.git`, undir `util/`

The `me_cleaner` program is outside the scope of this
article, so you should read their documentation.

Now run this:

    ifdtool -x rom.bin

Several files will be created, and the one you need to
operate on is named `flashregion_3_gbe.bin` so please
ensure that you have this file.

Read the notes below about how to use `nvmutils` programs,
operating on this file. When you're done, you can insert the
modified GbE file back into your ROM image, like so:

    ifdtool -i gbe:flashregion_3_gbe.bin rom.bin

This will create the file `rom.bin.new`, which contains
your modified GbE section with the NVM images inside; this
includes your MAC address.

Refer to flashrom documentation. You may flash the new ROM
like so, if running on the same system and the regions are
read-write:

    flashrom -p internal -w rom.bin.new

Newer versions of flashrom support flashing just the specified
region, like so:

    flashrom -p internal --ifd -i gbe -w rom.bin.new

If you're running flashrom from host CPU on the target
system, and it's dual flash, you can just flash the
concatenated image, which you created earlier by running
the `cat` program; dual-IC flash configurations appear to
your operating system as one large flash area, as though
it were a single chip.

If you're using an external programmer, you should change
the `-p internal` parameter to something else. In this
situation, you should re-split the file accordingly, if
you have a dual-IC flash set, like so:

	dd if=rom.bin.new of=spi2.rom bs=1M skip=8
	dd if=rom.bin.new of=spi1.rom bs=1M count=8

These files would then be flashed externally, separately,
using an external programmer.

The *above* example (using `dd`) is for setups with 12MB
flash, where you have 8MB as SPI1 and 4MB as SPI2. SPI1
would contain the IFD, and SPI2 is the upper flash area
containing your bootblock; GbE is probably located in
SPI1. You should adjust the above parameters, according
to your configuration.

How to compile source code
==========================

The nvmutils programs will work just fine, on any BSD operating
system, or unix-like system such as GNU+Linux, Chimera Linux or
Alpine Linux. You must be sure to have toolchains installed, for
building; a normal libc, C compiler and linker should be enough.
GCC and LLVM have all these things included, so use whichever one
you want.

GCC and Clang both work quite well, and `nvmutils` programs only
use standard C libraries. As such, you do not need to install any
third party header files.

Build the utilities
-------------------

First, ensure that the current working directory is your
copy of the nvmutils source code!

You may run this in your terminal:

    make

Making changes
--------------

You can re-run `make` to re-build the software, if you've
made modifications. Patches welcome!

Regarding endianness
--------------------

The programs in `nvmutils` have been written with portability
in mind. The code is endian-independent, so it should work on
any system. Furthermore, portable C99 integer types are used
extensively.

Patches welcome!
================

Modular design
--------------

The code is cleanly written, and modular. It is written
precisely with the Unix philosophy in mind: write *one*
program that performs *one* task in the most efficient
manner possible.

Thus, specific tasks are implemented by single-use programs
within nvmutils. These programs share common code with each
other. If you see some code in nvmutils that you think could
be improved, patches are very welcome!

Use of non-portable data structures is avoided entirely.

How to use nvmutils
===================

Here, you may learn how to use each program:

nvmmac
------

The `nvmmac` program lets you change the MAC address. It sets
a valid checksum, after changing the MAC address. This program
operates on *both* NVM parts, but it will only modify a given
part if the existing checksum is correct. It will exit with zero
status if at least one part is modified; otherwise, it will
exit with non-zero status (one).

How to use (the MAC address in just an example):

    nvmmac gbe.bin 00:de:ad:be:ef:00

The *reason* nvmmac doesn't alter a part with an existing
invalid checksum, is precisely so that if the algorithm
changes in future Intel PHYs, nvmmac will just fail and
not modify your file. This is because the checksum would
then be invalid, at all times. However, correct NVM parts
with otherwise invalid checksums do exist, and can be
correct if you use the `nvmfix` program as defined in
this document.

nvmcheck
--------

The `nvmcheck` program shows a hexdump of both NVM parts, and
tells you whether each one is valid (as per checksum calculation).

How to use:

    nvmcheck gbe.bin

nvmcp
-----

The `nvmcp` program copies one NVM part to another. It copies
the *entire* 4KB part, within the 8KB file.

Overwrite part 0 with the contents of part 1:

    nvmcp gbe.bin 1

Overwrite part 1 with the contents of part 0:

    nvmcp gbe.bin 0

nvmswap
-------

The `nvmswap` program simply swaps both 4KB parts in the GbE
file. It does this, via simple XOR swaps.

How to use:

    nvmswap gbe.bin

nvmfix
------

The `nvmfix` program calculates and sets a valid checksum, on
the desired NVM part. Usage:

Fix part 0:

    nvmfix gbe.bin 0

Fix part 1:

    nvmfix gbe.bin 1

nvmbrick
--------

The `nvmbrick` program intentionally sets an invalid checksum, on
the desired NVM part. Usage:

Invalidate part 0:

    nvmbrick gbe.bin 0

Invalidate part 1:

    nvmbrick gbe.bin 1

That is all.

LICENSE
=======

The nvmutils software and documentation are released under the following
terms (Expat license):

Copyright 2022 Leah Rowe

Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
